/*
 * Malware Development for Ethical Hackers
 * encrypt.c
 * encrypt malware configuration file
 * author: @cocomelonc
*/

#include <windows.h>
#include <wininet.h>
#include <wincrypt.h>
#include <stdio.h>

#define AES_BLOCK_SIZE 16
#define IN_CHUNK_SIZE (AES_BLOCK_SIZE * 10)
#define OUT_CHUNK_SIZE (IN_CHUNK_SIZE * 2)

void encryptFile(const char* inputFile, const char* outputFile, const char* aesKey) {
  HCRYPTPROV hCryptProv = 0;
  HCRYPTKEY hKey = 0;
  HANDLE hInputFile = INVALID_HANDLE_VALUE;
  HANDLE hOutputFile = INVALID_HANDLE_VALUE;

  // Open input file for reading
  hInputFile = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hInputFile == INVALID_HANDLE_VALUE) {
    return;
  }

  // Check file size
  LARGE_INTEGER fileSize;
  if (!GetFileSizeEx(hInputFile, &fileSize)) {
    CloseHandle(hInputFile);
    return;
  }

  // Encrypt only if file size is less than 128MB
  if (fileSize.QuadPart > 128 * 1024 * 1024) {
    CloseHandle(hInputFile);
    return;
  }

  // Create output file for writing
  hOutputFile = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hOutputFile == INVALID_HANDLE_VALUE) {
    CloseHandle(hInputFile);
    return;
  }

  // Cryptographic service provider
  if (!CryptAcquireContextA(&hCryptProv, NULL, "Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
  }

  HCRYPTHASH hHash;
  if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
  }

  if (!CryptHashData(hHash, (BYTE*)aesKey, strlen(aesKey), 0)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
  }

  if (!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash, 0, &hKey)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
  }

  const size_t chunk_size = OUT_CHUNK_SIZE;
  BYTE* chunk = (BYTE*)malloc(chunk_size);
  DWORD out_len = 0;

  BOOL isFinal = FALSE;
  DWORD readTotalSize = 0;
  BOOL bResult = FALSE;

  while (bResult = ReadFile(hInputFile, chunk, IN_CHUNK_SIZE, &out_len, NULL)) {
    if (0 == out_len) {
      break;
    }
    readTotalSize += out_len;
    if (readTotalSize >= fileSize.QuadPart) {
      isFinal = TRUE;
    }

    if (!CryptEncrypt(hKey, (HCRYPTHASH)NULL, isFinal, 0, chunk, &out_len, chunk_size)) {
      break;
    }

    DWORD written = 0;
    if (!WriteFile(hOutputFile, chunk, out_len, &written, NULL)) {
      break;
    }

    memset(chunk, 0, chunk_size);
  }

  if (hKey != 0) {
    CryptDestroyKey(hKey);
  }
  if (hCryptProv != 0) {
    CryptReleaseContext(hCryptProv, 0);
  }
  if (hInputFile != INVALID_HANDLE_VALUE) {
    CloseHandle(hInputFile);
  }
  if (hOutputFile != INVALID_HANDLE_VALUE) {
    CloseHandle(hOutputFile);
  }

  free(chunk);
}

int main() {
  const char *inputFile = "config.txt";
  const char *encryptedFile = "config.txt.aes";
  const char *encryptionKey = "ThisIsASecretKey";
  // encrypt configuration file
  encryptFile(inputFile, encryptedFile, encryptionKey);
  return 0;
}
